/*****************************************************************
 MYD Engine v0.1

 File: myd_importer.cpp
 Created: 02/07/09
*****************************************************************/
#include "myd_importer.h"
#include "graphics/myd_renderer.h"

using namespace myd;

//----------------------------------------------------------------constructor
Importer::Importer(Renderer *tm_Renderer)
:
wn_Renderer(tm_Renderer)
{}

//----------------------------------------------------------------destructor
Importer::~Importer(void)
{
	// delete all the prototype sprites
	for( std::map<std::string, Sprite*>::iterator it = spritesMap.begin(), e = spritesMap.end(); it != e; )
	{
		Sprite* pkSprite = it->second;
		
		spritesMap.erase(it++);
		
		delete pkSprite;
		pkSprite = NULL;
	}
}

//----------------------------------------------------------------createSprite
bool Importer::createSprite (const char* name, Sprite& tm_Sprite)
{
	Sprite* pkSprite = spritesMap[name];

	if(!pkSprite)
		return false;

	pkSprite->clone(tm_Sprite);

	return true;
}
//----------------------------------------------------------------getTexture
Texture::Ptr Importer::getTexture (const char* fileName)
{
	Texture::Ptr tm_Texture = texturesMap[fileName];
	Texture::Ptr pkNewTexture(new Texture(*tm_Texture));
	return pkNewTexture;
}
//----------------------------------------------------------------------
Tilemap* Importer::createTrueMap(char *fileName)
{
	//init ameThingy
	ameThing.ReadFile(fileName);

	//filename issues
	char bitmap[100];
	strcpy(bitmap, "../../res/");
	strcat(bitmap, ameThing.szDefBitmapFile);

	//create tilemap
	Tilemap *tm_tilemap = new Tilemap();

	int totalTilesCount = ameThing.usTileCountX * ameThing.usTileCountY;
	tm_tilemap->wn_vertices = new TextureVertex[4 * totalTilesCount];

	//create texture
	Texture::Ptr tm_texture = importTextureFromFile(bitmap, ameThing.ulColorKey);
	tm_tilemap->wn_texture = tm_texture;

	int xoff; int yoff;
	
	//create vertexes
	for (int i=0; i<totalTilesCount; i+=4)
	{
		float fTexWidth = static_cast<float>(tm_texture->getWidth());
		float fTexHeight = static_cast<float>(tm_texture->getHeight());
		
		// calculate the texture coordinates
		xoff = i * ameThing.usBitmapWidth;
		yoff = 1;

		float sizeX = ameThing.usTileWidth/100;
		float sizeY = ameThing.usBitmapHeight/100;

		float fU1 = xoff / ameThing.usBitmapWidth;
		float fU2 = 1.0f;

		float fV1 = yoff / ameThing.usBitmapHeight;
		float fV2 = 0.1f;

		tm_tilemap->wn_vertices[i].X = -0.5f;
		tm_tilemap->wn_vertices[i].Y = -0.5;
		tm_tilemap->wn_vertices[i].Z = 1.0f;
		tm_tilemap->wn_vertices[i].U = 0.0;//fU1;
		tm_tilemap->wn_vertices[i].V = 1.0;//fV2;

		tm_tilemap->wn_vertices[i+1].X = -0.5f;
		tm_tilemap->wn_vertices[i+1].Y = 0.5;
		tm_tilemap->wn_vertices[i+1].Z = 1.0f;
		tm_tilemap->wn_vertices[i+1].U = 0.0;//fU1;//
		tm_tilemap->wn_vertices[i+1].V = 0.0;//fV1;//

		tm_tilemap->wn_vertices[i+2].X = 0.5f;
		tm_tilemap->wn_vertices[i+2].Y = -0.5f;
		tm_tilemap->wn_vertices[i+2].Z = 1.0f;
		tm_tilemap->wn_vertices[i+2].U = 1.0;//fU2;//
		tm_tilemap->wn_vertices[i+2].V = 1.0;//fV2;

		tm_tilemap->wn_vertices[i+3].X = 0.5f;
		tm_tilemap->wn_vertices[i+3].Y = 0.5f;
		tm_tilemap->wn_vertices[i+3].Z = 1.0f;
		tm_tilemap->wn_vertices[i+3].U = 1.0;//fU2;
		tm_tilemap->wn_vertices[i+3].V = 0.0;//fV1;//
	}
	return tm_tilemap;
}

//----------------------------------------------------------------------
Tilemap* Importer::createSpriteMap(char *fileName, int startingX, int startingY)
{
	//init ameThingy
	ameThing.ReadFile(fileName);

	//create tilemap
	Tilemap *tm_tilemap = new Tilemap();
	
	//filename issues
	char filename[100];
	strcpy(filename, "../../res/");
	strcat(filename, ameThing.szDefBitmapFile);

	//create sprtiles
	int totalTilesCount = ameThing.usTileCountX * ameThing.usTileCountY;
		
	int posX = startingX;
	int posY = startingY;
	int positionIndex = 1;
	int youDontMind = ameThing.usBitmapWidth / ameThing.usTileWidth;

	for(int i=0; i<totalTilesCount; i++)
	{
		//texture settings
		int xoff = 0;
		int yoff = 0;

		//texture offset by tilenum
		int H = 0; int V = 0;
		for (int j=0; j<ameThing.pbiBlock[i].sTileNum; j++){H++;
			if(H == youDontMind){H = 0;	V++;}
		}

		xoff = H * ameThing.usTileWidth;
		yoff = V * ameThing.usTileHeight;

		//sprite creation
		tm_tilemap->tilesVector.push_back(createSpriteFromFile(filename, xoff, yoff, 
															   ameThing.usTileWidth, 
															   ameThing.usTileHeight, 
															   ameThing.ulColorKey));
		
		//sprite settings
		tm_tilemap->tilesVector[i]->setPos(posX, posY, 5);
		tm_tilemap->tilesVector[i]->setDim(ameThing.usTileWidth+1, ameThing.usTileHeight+1);
		
		//collision tag
		if(ameThing.pbiBlock[i].ucFlags == true)
			tm_tilemap->tilesVector[i]->setCollisionable(true);
		else
			tm_tilemap->tilesVector[i]->setCollisionable(false);
		
		//tile positioning
		posX += ameThing.usTileWidth;
		if (positionIndex == ameThing.usTileCountX)
		{
			posY -= ameThing.usTileHeight;
			posX = startingX;
			positionIndex = 0;
		}
		positionIndex ++;
	}
	return tm_tilemap;
}
//----------------------------------------------------------------------
Sprite* Importer::createSpriteFromFile (const char* name, int xoff, int yoff, 
									 int width, int height, unsigned long colorKey)
{
	Sprite *tm_Sprite = new Sprite();
	Texture::Ptr tm_Texture = importTextureFromFile(name, colorKey);

	// set attributes to sprite
	tm_Sprite->setTexture( tm_Texture );
	tm_Sprite->setName(name);
	tm_Sprite->setTextureArea(xoff, yoff, width, height);

	return tm_Sprite;
}
//----------------------------------------------------------------------
Texture::Ptr Importer::importTextureFromFile (const char* name, unsigned long colorKey)
{
	assert(wn_Renderer);
	
	// create the new texture
	Texture::Ptr tm_Texture = Texture::Ptr( new Texture(name, colorKey) );

	// add to map
	texturesMap[name] = tm_Texture;
	wn_Renderer->loadTexture(*tm_Texture);

	return tm_Texture;
}
//----------------------------------------------------------------------
bool Importer::importXFile(char* filename, Mesh3d &tm_mesh, LPDIRECT3DDEVICE9 tm_device)
{
	DWORD numMaterials;
	LPD3DXBUFFER materialsBuffer;

	HRESULT hr;
	hr = D3DXLoadMeshFromX(filename,
						   D3DXMESH_SYSTEMMEM,
						   tm_device,
						   NULL,
						   &materialsBuffer,
						   NULL,
						   &numMaterials,
						   &tm_mesh.wn_mesh);

	D3DMATERIAL9 *material;
	D3DXMATERIAL *tempMaterials = (D3DXMATERIAL*)materialsBuffer->GetBufferPointer();

	material = new D3DMATERIAL9[numMaterials];

	for(DWORD i = 0; i < numMaterials; i++){
		material[i] = tempMaterials[i].MatD3D;
		material[i].Ambient = material[i].Diffuse;
	}

	return true;
}